﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

#if !WINRT

using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

#else
using Windows.Devices.Input;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

#endif

namespace MishraReader.Windows.Controls
{
    public class ComboButton : HeaderedContentControl
    {
        public bool IsDropDownOpen
        {
            get { return (bool)GetValue(IsDropDownOpenProperty); }
            set { SetValue(IsDropDownOpenProperty, value); }
        }



        public double VerticalOffset
        {
            get { return (double)GetValue(VerticalOffsetProperty); }
            set { SetValue(VerticalOffsetProperty, value); }
        }



        public double HorizontalOffset
        {
            get { return (double)GetValue(HorizontalOffsetProperty); }
            set { SetValue(HorizontalOffsetProperty, value); }
        }



        public Thickness ArrowMargin
        {
            get { return (Thickness)GetValue(ArrowMarginProperty); }
            set { SetValue(ArrowMarginProperty, value); }
        }



        public HorizontalAlignment ArrowHorizontalAlignment
        {
            get { return (HorizontalAlignment)GetValue(ArrowHorizontalAlignmentProperty); }
            set { SetValue(ArrowHorizontalAlignmentProperty, value); }
        }

        public static readonly DependencyProperty ArrowHorizontalAlignmentProperty =
            DependencyProperty.Register("ArrowHorizontalAlignment", typeof(HorizontalAlignment), typeof(ComboButton), new UIPropertyMetadata(HorizontalAlignment.Center));

        

        // Using a DependencyProperty as the backing store for ArrowMargin.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ArrowMarginProperty =
            DependencyProperty.Register("ArrowMargin", typeof(Thickness), typeof(ComboButton), new UIPropertyMetadata(new Thickness(0,0,0,-1)));

        
        public static readonly DependencyProperty HorizontalOffsetProperty =
            DependencyProperty.Register("HorizontalOffset", typeof(double), typeof(ComboButton), new UIPropertyMetadata(-50D));

        

        // Using a DependencyProperty as the backing store for VerticalOffset.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty VerticalOffsetProperty =
            DependencyProperty.Register("VerticalOffset", typeof(double), typeof(ComboButton), new UIPropertyMetadata(-15D));

        

        public static readonly DependencyProperty IsDropDownOpenProperty = DependencyProperty.Register("IsDropDownOpen", typeof(bool), typeof(ComboButton), new UIPropertyMetadata(false, OnIsDropDownOpenChanged));

        private static void OnIsDropDownOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ComboButton element = (ComboButton)d;
            bool newValue = (bool)e.NewValue;
            bool oldValue = !newValue;

            if (newValue)
            {
                Mouse.Capture(element, CaptureMode.SubTree);

            }
            else
            {
                if (element.IsKeyboardFocusWithin)
                {
                    element.Focus();
                }
                if (element.HasCapture)
                {

                    Mouse.Capture(null);
                }
            }
        }

        private bool _isMouseOverItemsHost;
        private Panel _contentPart;

        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (IsDropDownOpen)
            {
                bool flag = (_contentPart != null) ? _contentPart.IsMouseOver : false;

                _isMouseOverItemsHost = flag;
            }

            base.OnMouseMove(e);
        }

        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            if (!_isMouseOverItemsHost && this.IsDropDownOpen)
            {
                Close();
                e.Handled = true;
            }

            base.OnMouseLeftButtonDown(e);
        }

        private void Close()
        {
            if (this.IsDropDownOpen)
            {
                base.SetCurrentValue(IsDropDownOpenProperty, false);
            }
        }

        protected override void OnLostMouseCapture(MouseEventArgs e)
        {
            if (Mouse.Captured != this)
            {
                if (e.OriginalSource == this)
                {
                    if ((Mouse.Captured == null) || !Helper.IsDescendant(this, Mouse.Captured as DependencyObject))
                    {
                        this.Close();
                    }
                }
                else if (Helper.IsDescendant(this, e.OriginalSource as DependencyObject))
                {
                    if ((this.IsDropDownOpen && (Mouse.Captured == null)))
                    {
                        Mouse.Capture(this, CaptureMode.SubTree);
                        e.Handled = true;
                    }
                }
                else
                {
                    this.Close();
                }
            }
            base.OnLostMouseCapture(e);
        }

        protected override void OnLostFocus(RoutedEventArgs e)
        {
            if (Mouse.Captured != this)
            {
                if (e.OriginalSource == this)
                {
                    if ((Mouse.Captured == null) || !Helper.IsDescendant(this, Mouse.Captured as DependencyObject))
                    {
                        this.Close();
                    }
                }
                else if (Helper.IsDescendant(this, e.OriginalSource as DependencyObject))
                {
                    if ((this.IsDropDownOpen && (Mouse.Captured == null)))
                    {
                        Mouse.Capture(this, CaptureMode.SubTree);
                        e.Handled = true;
                    }
                }
                else
                {
                    this.Close();
                }
            }
            base.OnLostFocus(e);
        }

        public override void OnApplyTemplate()
        {
            _contentPart = (Panel)GetTemplateChild("PART_Content");

            base.OnApplyTemplate();
        }

        private bool HasCapture
        {
            get
            {
                return (Mouse.Captured == this);
            }
        }

        static ComboButton()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ComboButton), new FrameworkPropertyMetadata(typeof(ComboButton)));
        }

        public class Helper
        {
            private static MethodInfo _methodInfo;

            static Helper()
            {
                var type = typeof(MenuBase);
                _methodInfo = type.GetMethod("IsDescendant", BindingFlags.NonPublic | BindingFlags.Static);
            }
            internal static bool IsDescendant(DependencyObject reference, DependencyObject node)
            {
                return (bool)_methodInfo.Invoke(null, new object[] { reference, node });
            }

        }
    }
}
